/**
  ************************************* Copyright ******************************
  * FileName   : ds18b20.c
  * Version    : v1.0
  * Author     : yychao
  * Date       : 2023-01-28
  * Description:
  * Function List:
  	1. ....
  	   <version>:
  <modify staff>:
  		  <data>:
   <description>:
  	2. ...
  ******************************************************************************
 */
#include "ds18b20.h"
#include "systick.h"
#include "log.h"
#include "oled.h"
#include "stdio.h"
#include "tim_delay.h"

ds18b20 ds18b20_data_st;



#define GPIO_DS18B20_0 GPIOE
#define GPIO_DS18B20_PIN_0 GPIO_PIN_7

#define GPIO_DS18B20_1 GPIOE
#define GPIO_DS18B20_PIN_1 GPIO_PIN_8

#define GPIO_DS18B20_2 GPIOE
#define GPIO_DS18B20_PIN_2 GPIO_PIN_9

#define GPIO_DS18B20_3 GPIOE
#define GPIO_DS18B20_PIN_3 GPIO_PIN_10

//#define DS18B20_H	(GPIO_DS18B20->PBSC = GPIO_DS18B20_PIN)
//#define DS18B20_L	(GPIO_DS18B20->PBC = GPIO_DS18B20_PIN)
//#define DS18B20_READ	(GPIO_ReadInputDataBit(GPIO_DS18B20, GPIO_DS18B20_PIN))

void DS18B20_H(ds18b20* ds18b20_st) {
    switch(ds18b20_st->read_num) {
    case 0:
        GPIO_DS18B20_0->PBSC = GPIO_DS18B20_PIN_0;
        break;
    case 1:
        GPIO_DS18B20_1->PBSC = GPIO_DS18B20_PIN_1;
        break;
    case 2:
        GPIO_DS18B20_2->PBSC = GPIO_DS18B20_PIN_2;
        break;
    case 3:
        GPIO_DS18B20_3->PBSC = GPIO_DS18B20_PIN_3;
        break;
    }
}
void DS18B20_L(ds18b20* ds18b20_st) {
    switch(ds18b20_st->read_num) {
    case 0:
        GPIO_DS18B20_0->PBC = GPIO_DS18B20_PIN_0;
        break;
    case 1:
        GPIO_DS18B20_1->PBC = GPIO_DS18B20_PIN_1;
        break;
    case 2:
        GPIO_DS18B20_2->PBC = GPIO_DS18B20_PIN_2;
        break;
    case 3:
        GPIO_DS18B20_3->PBC = GPIO_DS18B20_PIN_3;
        break;
    }

}
uint8_t DS18B20_READ(ds18b20* ds18b20_st) {
    switch(ds18b20_st->read_num) {
    case 0:
        return GPIO_ReadInputDataBit(GPIO_DS18B20_0, GPIO_DS18B20_PIN_0);
        break;
    case 1:
        return GPIO_ReadInputDataBit(GPIO_DS18B20_1, GPIO_DS18B20_PIN_1);
        break;
    case 2:
        return GPIO_ReadInputDataBit(GPIO_DS18B20_2, GPIO_DS18B20_PIN_2);
        break;
    case 3:
        return GPIO_ReadInputDataBit(GPIO_DS18B20_3, GPIO_DS18B20_PIN_3);
        break;
    }

}

void DS18B20_IN(ds18b20* ds18b20_st)
{
    GPIO_InitType GPIO_InitStructure = { 0 };
    switch(ds18b20_st->read_num) {
    case 0:
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE);

        GPIO_InitStructure.Pin        = GPIO_DS18B20_PIN_0;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitPeripheral(GPIO_DS18B20_0, &GPIO_InitStructure);
    case 1:
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE);

        GPIO_InitStructure.Pin        = GPIO_DS18B20_PIN_1;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitPeripheral(GPIO_DS18B20_1, &GPIO_InitStructure);
    case 2:
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE);

        GPIO_InitStructure.Pin        = GPIO_DS18B20_PIN_2;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitPeripheral(GPIO_DS18B20_2, &GPIO_InitStructure);
    case 3:
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE);

        GPIO_InitStructure.Pin        = GPIO_DS18B20_PIN_3;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitPeripheral(GPIO_DS18B20_3, &GPIO_InitStructure);
        break;
    }

}

void DS18B20_OUT(ds18b20* ds18b20_st)
{

    GPIO_InitType GPIO_InitStructure = { 0 };
    switch(ds18b20_st->read_num) {
    case 0:
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE);

        GPIO_InitStructure.Pin        = GPIO_DS18B20_PIN_0;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitPeripheral(GPIO_DS18B20_0, &GPIO_InitStructure);
    case 1:
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE);

        GPIO_InitStructure.Pin        = GPIO_DS18B20_PIN_1;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitPeripheral(GPIO_DS18B20_1, &GPIO_InitStructure);
    case 2:
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE);

        GPIO_InitStructure.Pin        = GPIO_DS18B20_PIN_2;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitPeripheral(GPIO_DS18B20_2, &GPIO_InitStructure);
    case 3:
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE);

        GPIO_InitStructure.Pin        = GPIO_DS18B20_PIN_3;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitPeripheral(GPIO_DS18B20_3, &GPIO_InitStructure);
        break;
    }
}



void DS18B20_RST(ds18b20* ds18b20_st)
{
    DS18B20_OUT(ds18b20_st);
    DS18B20_L(ds18b20_st);
    delay_us(750);
    DS18B20_H(ds18b20_st);
    delay_us(15);
}
uint8_t DS18B20_CHECK(ds18b20* ds18b20_st)
{
    uint8_t retry = 0;
    DS18B20_IN(ds18b20_st);
    while((DS18B20_READ(ds18b20_st))&&(retry < 200)) {
        retry++;
        delay_us(1);
    }
    if(retry >= 200) {
//        LOG_ERROR("The device Ds18b20[%d] is nonexistent 1 \r\n", ds18b20_st->read_num);
        return 1;
    } else {
        retry = 0;
    }
    while((!DS18B20_READ(ds18b20_st))&&(retry < 240)) {
        retry++;
        delay_us(1);
    }
    if(retry >= 240) {
//        LOG_ERROR("The device Ds18b20[%d] is nonexistent 2 \r\n", ds18b20_st->read_num);
        return 1;
    } else {
        return 0;
    }
}
uint8_t DS18B20_READ_BIT(ds18b20* ds18b20_st)
{
    uint8_t data = 0;
    DS18B20_OUT(ds18b20_st);
    DS18B20_L(ds18b20_st);
    delay_us(2);
    DS18B20_H(ds18b20_st);
    DS18B20_IN(ds18b20_st);
    delay_us(12);
    if(DS18B20_READ(ds18b20_st)) {
        data = 1;
    } else {
        data = 0;
    }
    delay_us(50);
    return data;
}
uint8_t DS18B20_READ_BYTE(ds18b20* ds18b20_st)
{
    uint8_t data = 0;
    for(uint8_t i = 0; i < 8; i++) {
        data >>= 1;
        if(DS18B20_READ_BIT(ds18b20_st)) {
            data |= 0x80;
        }
    }
    return data;
}

void DS18B20_WRITE_BYTE(ds18b20* ds18b20_st, uint8_t data)
{
    uint8_t bit = 0;
    DS18B20_OUT(ds18b20_st);
    for(uint8_t i = 0; i < 8; i++) {
        bit = data&0x01;
        data >>= 1;
        if(bit) {
            DS18B20_L(ds18b20_st);
            delay_us(2);
            DS18B20_H(ds18b20_st);
            delay_us(60);
        } else {
            DS18B20_L(ds18b20_st);
            delay_us(60);
            DS18B20_H(ds18b20_st);
            delay_us(2);
        }
    }
}

uint8_t DS18B20_INI(ds18b20* ds18b20_st)
{
    DS18B20_RST(ds18b20_st);
    return DS18B20_CHECK(ds18b20_st);
}
void DS18B20_START_CONV(ds18b20* ds18b20_st)
{
    DS18B20_RST(ds18b20_st);
    DS18B20_CHECK(ds18b20_st);
    DS18B20_WRITE_BYTE(ds18b20_st, 0xcc);
    DS18B20_WRITE_BYTE(ds18b20_st, 0x44);
}
void DS18B20_READ_RAM(ds18b20* ds18b20_st)
{
    DS18B20_RST(ds18b20_st);
    DS18B20_CHECK(ds18b20_st);
    DS18B20_WRITE_BYTE(ds18b20_st, 0xcc);
    DS18B20_WRITE_BYTE(ds18b20_st, 0xbe);
}
void DS18B20_GET_TEMP(ds18b20* ds18b20_st)
{
    float TEMPERATURE = 0;
    uint16_t TEM = 0;
    uint8_t TH = 0, TL = 0;
    DS18B20_RST(ds18b20_st);
    DS18B20_CHECK(ds18b20_st);
    DS18B20_WRITE_BYTE(ds18b20_st, 0xcc);
    DS18B20_WRITE_BYTE(ds18b20_st, 0x44);
    DS18B20_RST(ds18b20_st);
    DS18B20_CHECK(ds18b20_st);
    DS18B20_WRITE_BYTE(ds18b20_st, 0xcc);
    DS18B20_WRITE_BYTE(ds18b20_st, 0xbe);
    TL = DS18B20_READ_BYTE(ds18b20_st);
    TH = DS18B20_READ_BYTE(ds18b20_st);
    TEM = TH;
    TEM <<= 8;
    TEM |= TL;
    if((TH == TL)&&(TH == 0xff)) {
        ds18b20_st->status[ds18b20_st->read_num] = 1;
        TEMPERATURE = 0;
    } else {
        ds18b20_st->status[ds18b20_st->read_num] = 0;
        TEMPERATURE = TEM * 0.0625;
    }
    ds18b20_st->tem_val[ds18b20_st->read_num] = TEMPERATURE;
    ds18b20_st->val_16bit[ds18b20_st->read_num] = ds18b20_st->tem_val[ds18b20_st->read_num]*10;
//    LOG_DEBUG("DS18B20[%d] = %f %d\r\n", ds18b20_st->read_num, ds18b20_st->tem_val[ds18b20_st->read_num],
//              ds18b20_st->val_16bit[ds18b20_st->read_num]);
//    LOG_DEBUG("TL:%d TH:%d TEMP:%f\r\n",TL, TH, TEMPERATURE);
}